package com.hzhanghuan.floatmenu;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.ColorStateList;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.os.Handler;
import android.support.annotation.ColorInt;
import android.support.annotation.ColorRes;
import android.support.annotation.DrawableRes;
import android.support.design.widget.FloatingActionButton;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AnticipateOvershootInterpolator;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 基于FloatingActionBottom的浮动菜单
 * Created by Administrator on 2016/7/5.
 */
public class FloatMenuButton extends ViewGroup {


    private int mSpace;

    private List<FloatingActionButton> actionButtons = new ArrayList<>();

    public FloatingActionButton mFloatingActionButton;

    private int menuSize;

    private ValueAnimator valueAnimator;

    private Handler mainHandler = new Handler();

    private boolean status = false;


    public FloatMenuButton(Context context) {
        super(context);
        init(context);
    }


    public FloatMenuButton(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }


    public FloatMenuButton(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }


    private void init(Context context) {
        mSpace = (int) (getResources().getDisplayMetrics().density * 5);
        menuSize = getResources().getDimensionPixelSize(R.dimen.menu_size);
        mFloatingActionButton = new FloatingActionButton(context);
        mFloatingActionButton.setOnClickListener(new OnMenuClickListener());
        addView(mFloatingActionButton);
        mFloatingActionButton.getLayoutParams();
    }


    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        ViewGroup view = (ViewGroup) getParent();
        view.setClipChildren(false);
        for (int i = 0; i < actionButtons.size(); i++) {
            FloatingActionButton actionButton = actionButtons.get(i);
            actionButton.setTranslationY(actionButton.getHeight());
        }
    }


    @Override
    protected LayoutParams generateDefaultLayoutParams() {
        MarginLayoutParams marginLayoutParams = new MarginLayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
        int elevation = (int) mFloatingActionButton.getCompatElevation();
        marginLayoutParams.setMargins(elevation, elevation, elevation, elevation);
        return marginLayoutParams;
    }


    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        MarginLayoutParams lp = (MarginLayoutParams) mFloatingActionButton.getLayoutParams();
        int left = getPaddingLeft() + lp.leftMargin;
        int right = left + menuSize;
        int bottom = (b - t) - getPaddingBottom() - lp.bottomMargin;
        int top = bottom - menuSize;
        //menu按钮位置
        mFloatingActionButton.layout(left, top, right, bottom);
        bottom = top - lp.topMargin;
        for (int i = 0; i < actionButtons.size(); i++) {
            lp = (MarginLayoutParams) mFloatingActionButton.getLayoutParams();
            bottom = bottom - mSpace - lp.bottomMargin;
            top = bottom - menuSize;
            actionButtons.get(i).layout(left, top, right, bottom);
            bottom = top - lp.topMargin;
        }
    }


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        MarginLayoutParams lp = (MarginLayoutParams) mFloatingActionButton.getLayoutParams();
        int width = menuSize + getPaddingLeft() + getPaddingRight() + lp.leftMargin + lp.rightMargin;
        int height = menuSize + getPaddingTop() + getPaddingBottom() + lp.topMargin + lp.bottomMargin;
        ensureTarget();
        if (actionButtons.size() == 0) {
            setMeasuredDimension(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
                    MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
            return;
        }
        for (int i = 0; i < actionButtons.size(); i++) {
            FloatingActionButton actionButton = actionButtons.get(i);
            lp = (MarginLayoutParams) actionButton.getLayoutParams();
            height += (menuSize + mSpace + lp.bottomMargin + lp.topMargin);
            actionButton.measure(widthMeasureSpec, heightMeasureSpec);
            actionButton.setTranslationY(actionButton.getMeasuredHeight());
        }

        setMeasuredDimension(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
                MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
    }


    protected void ensureTarget() {
        actionButtons.clear();
        for (int i = 0; i < getChildCount(); i++) {
            View childView = getChildAt(i);
            if (childView instanceof FloatingActionButton && childView != mFloatingActionButton) {
                actionButtons.add((FloatingActionButton) childView);

            }
        }
    }


    public void setMenuRipperColor(@ColorInt int color) {
        mFloatingActionButton.setRippleColor(color);
    }


    public void setSpaceSize(int size) {
        this.mSpace = (int) (getResources().getDisplayMetrics().density * size);
    }


    public void setSpaceSizePixel(int size) {
        this.mSpace = size;
    }


    /**
     * menu的图标
     *
     * @param iconRes
     */
    public void setMenuIcon(@DrawableRes int iconRes) {
        mFloatingActionButton.setImageResource(iconRes);
    }


    public void setMenuColorRes(@ColorRes int colorRes) {
        setMenuColor(getResources().getColor(colorRes));
    }


    public void setMenuColor(@ColorInt int color) {
        ColorStateList colorStateList = ColorStateList.valueOf(color);
        setMenuColorStateList(colorStateList);
    }


    public void setMenuColorStateList(ColorStateList colorStateList) {
        try {
            Method method = FloatingActionButton.class.getDeclaredMethod("getImpl");
            method.setAccessible(true);
            Object floatingActionButtonImpl = method.invoke(mFloatingActionButton);
            Field ripperField = FloatingActionButton.class.getDeclaredField("mRippleColor");
            Field borderField = FloatingActionButton.class.getDeclaredField("mBorderWidth");
            ripperField.setAccessible(true);
            borderField.setAccessible(true);
            int ripple = ripperField.getInt(mFloatingActionButton);
            int border = borderField.getInt(mFloatingActionButton);
            method = floatingActionButtonImpl.getClass().getDeclaredMethod("setBackgroundDrawable"
                    , ColorStateList.class, PorterDuff.Mode.class, int.class, int.class);
            method.setAccessible(true);
            PorterDuff.Mode mode = mFloatingActionButton.getBackgroundTintMode();
            method.invoke(floatingActionButtonImpl, colorStateList, mode, ripple, border);

//            getImpl().setElevation(elevation);
//            getImpl().setPressedTranslationZ(pressedTranslationZ);
            method = Class.forName("android.support.design.widget.FloatingActionButtonImpl").getDeclaredMethod("updatePadding");
            method.setAccessible(true);
            method.invoke(floatingActionButtonImpl);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }


    }


    public void setMenuItemView(FloatingActionButton... menuItemView) {
        if (getChildCount() > 1) {
            removeViews(1, getChildCount() - 1);
        }
        for (int i = 0; i < menuItemView.length; i++) {
            menuItemView[i].setVisibility(GONE);
            addView(menuItemView[i]);
        }
    }


    /**
     * 菜单按钮的单击事件
     */
    private class OnMenuClickListener implements OnClickListener {

        @Override
        public void onClick(View v) {
            if (status) {
                //关闭菜单
                closeMenu();
            } else {
                //打开菜单
                openMenu();
                //记录状态
                status = true;
            }

        }
    }


    private void openMenu() {
        for (int i = 0; i < actionButtons.size(); i++) {
            actionButtons.get(i).setVisibility(View.VISIBLE);
            actionButtons.get(i).setAlpha(0.0f);
        }
        for (int i = 0; i < actionButtons.size(); i++) {
            FloatingActionButton actionButton = actionButtons.get(i);
//            actionButton.setTranslationY(actionButton.getHeight());
            actionButton.animate().cancel();
            actionButton.animate()
                    .setListener(null)
                    .setInterpolator(new AnticipateOvershootInterpolator(3.5f))
                    .alpha(1)
                    .translationY(0)
                    .setDuration(400)
                    .setStartDelay(i * (100))
                    .start();
        }
    }


    private void closeMenu() {
        for (int i = 0; i < actionButtons.size(); i++) {
            FloatingActionButton actionButton = actionButtons.get(i);
            actionButton.animate().cancel();
            actionButton.animate()
                    .setInterpolator(new AnticipateOvershootInterpolator(1.0f))
                    .alpha(0)
                    .translationY(actionButton.getHeight())
                    .setDuration(200)
                    .setStartDelay((actionButtons.size() - 1 - i) * (100))
                    .setListener((i == 0) ? animatorListener : null)
                    .start();
        }
    }


    /**
     * 监听关闭动画,动画完成后隐藏itemView
     */
    Animator.AnimatorListener animatorListener = new AnimatorListenerAdapter() {
        @Override
        public void onAnimationEnd(Animator animation) {
            for (int i = 0; i < actionButtons.size(); i++) {
                actionButtons.get(i).setVisibility(View.GONE);
            }
            status = false;
        }
    };


}
